/**   
 * Copyright 2011 COMERE Harold
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package etrl.resources;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;

import com.google.gwt.user.client.Window;
import com.googlecode.gwtgl.binding.WebGLRenderingContext;
import com.googlecode.gwtgl.binding.WebGLTexture;

/**
 * \class Resources
 * \brief Singleton class used to load textures resources at start up
 * then to access to this resources using resource name.
 * @author harold
 *
 */
public class Resources
{
	/**
	 * Singleton instance
	 */
	private static Resources _instance = null;

	/**
	 * GL context
	 */
	private WebGLRenderingContext _gl;
	
	/**
	 * Array containing all resources to load
	 */
	private ArrayList <AResource> _resources;
	
	/**
	 * Map mapping texture file paths with loaded textures
	 */
	private TreeMap <String, TextureResource> _textures;

	/**
	 * \brief Initializes the resources singleton
	 */
	private Resources()
	{
		_resources = new ArrayList <AResource>();
		_textures = new TreeMap <String, TextureResource>();
	}
	
	/**
	 * \brief Gets the resources instance
	 * @return Resources instance
	 */
	public static Resources instance()
	{
		if(_instance == null)
			_instance = new Resources();
	
		return _instance;
	}
	
	/**
	 * \brief Sets the GL context.
	 * It is set by the viewer at its creation.
	 * @param[in] gl the context
	 */
	public void setGLContext(WebGLRenderingContext gl)
	{
		_gl = gl;
	}
	
	/**
	 * \brief Launches all resources loading
	 */
	public void loadResources()
	{
		// Browse the resources array and launch all loadings
		for(Iterator <AResource> it = _resources.iterator(); it.hasNext();)
		{
			it.next().load();
		}
	}

	/**
	 * \brief Adds a new texture to loading file
	 * @param[in] filePath file path of the texture to laod
	 * @param[in] generateMipmaps if true, mipmaps will be generated for this texture, else not
	 */
	public void addTextureToLoad(String filePath, boolean generateMipmaps)
	{
		// First check if the requested texture isnt loading or loaded
		// If already loaded / loading, the texture map contains an entry for the file path
		// In this case do nothing.
		if(!_textures.containsKey(filePath))
		{
			// Well there is no entry for the given file path, create the resource
			TextureResource textureResource = new TextureResource(_gl, filePath, generateMipmaps);
			
			// Set the texture ready to load
			_resources.add(textureResource);

			// And add the texture in texture map
			_textures.put(filePath, textureResource);
		}
	}
	
	/**
	 * \brief Browses resources currently loading to detect those which are terminated
	 * @return resource still loading number
	 */
	public int checkResourceLoad()
	{
		int index = 0;
		
		while(index < _resources.size())
		{
			if(_resources.get(index).isLoaded())
			{
				if(! _resources.get(index).loadingIsSuccess())
				{
					Window.alert("Oh, oh ... Resource [" + _resources.get(index).getFilePath() + "] loading failed ;-(");
				}
					
				_resources.remove(index);
			}
			else
				++index;
		}
		
		return _resources.size();
	}
	
	/**
	 * \brief Texture object id getter
	 * @param[in] filePath file path of the texture to get
	 * @return texture object id if the texture is loaded, else null
	 */
	public WebGLTexture getTexture(String filePath)
	{
		if(_textures.containsKey(filePath))
			return _textures.get(filePath).getTextureObjectId();
		else
			return null;
	}
	
	/**
	 * \brief Clear all currently loaded resources
	 */
	public void clearResources()
	{
		// Clear the currently loading resources
		_resources.clear();
		
		// Release loaded texture objects
		for(Iterator <TextureResource> it = _textures.values().iterator(); it.hasNext();)
		{
			it.next().release();
		}
		
		_textures.clear();
		
	}
}
